package net.alteiar.ui.algorithms;

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.filechooser.FileNameExtensionFilter;

import net.alteiar.images.BasicImage;
import net.alteiar.images.IDrawable;
import net.alteiar.ui.MovablePanel;
import net.alteiar.ui.ZoomablePanel;
import net.alteiar.ui.listener.MoveListener;
import net.alteiar.ui.listener.ZoomListener;

public class PanelAlgorithms extends JPanel implements ActionListener {
	private static final long serialVersionUID = 1L;

	private final ZoomablePanel<IDrawable> panelImg;
	private final BasicImage img;

	private final JComboBox<PanelAlgorithmsDetails> comboBoxAlgorithm;
	private final JProgressBar progressBar;

	private final JPanel panelHyperParams;

	public PanelAlgorithms(BasicImage img) {
		this.img = img;

		GridBagLayout gridBagLayout = new GridBagLayout();
		gridBagLayout.columnWidths = new int[] { 0, 0, 33, 0, 0, 0 };
		gridBagLayout.rowHeights = new int[] { 0, 0, 0, 0, 0, 0, 0, 0 };
		gridBagLayout.columnWeights = new double[] { 0.0, 0.0, 0.0, 0.0, 1.0,
				Double.MIN_VALUE };
		gridBagLayout.rowWeights = new double[] { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0,
				0.0, Double.MIN_VALUE };
		setLayout(gridBagLayout);

		panelImg = new ZoomablePanel<IDrawable>(img);
		MovablePanel panelImage = new MovablePanel(panelImg);
		panelImage.setPreferredSize(new Dimension(800, 600));
		MoveListener moveListener = new MoveListener(panelImage);
		panelImg.addMouseWheelListener(new ZoomListener(panelImg));
		panelImg.addMouseMotionListener(moveListener);
		panelImg.addMouseListener(moveListener);

		comboBoxAlgorithm = new JComboBox<>();
		PanelAlgorithmClustering clustering = new PanelAlgorithmClustering();
		clustering.addActionListener(this);

		PanelAlgorithmEdgeDetector edgeDetector = new PanelAlgorithmEdgeDetector();
		edgeDetector.addActionListener(this);

		PanelAlgorithmEdgeDetectorSobel edgeDetectorSobel = new PanelAlgorithmEdgeDetectorSobel();
		edgeDetectorSobel.addActionListener(this);

		comboBoxAlgorithm.addItem(clustering);
		comboBoxAlgorithm.addItem(edgeDetector);
		comboBoxAlgorithm.addItem(edgeDetectorSobel);
		comboBoxAlgorithm.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				changedAlgorithm();
			}
		});

		GridBagConstraints gbc_comboBox = new GridBagConstraints();
		gbc_comboBox.gridwidth = 4;
		gbc_comboBox.insets = new Insets(0, 0, 5, 5);
		gbc_comboBox.fill = GridBagConstraints.HORIZONTAL;
		gbc_comboBox.gridx = 0;
		gbc_comboBox.gridy = 0;
		add(comboBoxAlgorithm, gbc_comboBox);

		GridBagConstraints gbc_panelImage = new GridBagConstraints();
		gbc_panelImage.gridheight = 7;
		gbc_panelImage.fill = GridBagConstraints.BOTH;
		gbc_panelImage.gridx = 4;
		gbc_panelImage.gridy = 0;
		add(panelImage, gbc_panelImage);

		panelHyperParams = new JPanel();
		GridBagConstraints gbc_panelHyperParams = new GridBagConstraints();
		gbc_panelHyperParams.gridheight = 2;
		gbc_panelHyperParams.gridwidth = 4;
		gbc_panelHyperParams.insets = new Insets(0, 0, 5, 5);
		gbc_panelHyperParams.fill = GridBagConstraints.BOTH;
		gbc_panelHyperParams.gridx = 0;
		gbc_panelHyperParams.gridy = 1;
		add(panelHyperParams, gbc_panelHyperParams);

		progressBar = new JProgressBar();
		GridBagConstraints gbc_progressBar = new GridBagConstraints();
		gbc_progressBar.fill = GridBagConstraints.HORIZONTAL;
		gbc_progressBar.gridwidth = 4;
		gbc_progressBar.insets = new Insets(0, 0, 5, 5);
		gbc_progressBar.gridx = 0;
		gbc_progressBar.gridy = 3;
		add(progressBar, gbc_progressBar);

		JButton buttonReset = new JButton("Reset");
		GridBagConstraints gbc_buttonReset = new GridBagConstraints();
		gbc_buttonReset.gridwidth = 4;
		gbc_buttonReset.insets = new Insets(0, 0, 5, 5);
		gbc_buttonReset.gridx = 0;
		gbc_buttonReset.gridy = 4;
		add(buttonReset, gbc_buttonReset);
		buttonReset.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				doReset();
			}
		});

		JButton btnExecute = new JButton("Execute");
		GridBagConstraints gbc_btnExecute = new GridBagConstraints();
		gbc_btnExecute.gridwidth = 4;
		gbc_btnExecute.insets = new Insets(0, 0, 5, 5);
		gbc_btnExecute.gridx = 0;
		gbc_btnExecute.gridy = 5;
		add(btnExecute, gbc_btnExecute);

		JButton btnOpen = new JButton("Open");
		GridBagConstraints gbc_btnOpen = new GridBagConstraints();
		gbc_btnOpen.gridwidth = 2;
		gbc_btnOpen.insets = new Insets(0, 0, 0, 5);
		gbc_btnOpen.gridx = 0;
		gbc_btnOpen.gridy = 6;
		add(btnOpen, gbc_btnOpen);

		JButton btnSaveToFile = new JButton("Save");
		GridBagConstraints gbc_btnSaveToFile = new GridBagConstraints();
		gbc_btnSaveToFile.gridwidth = 2;
		gbc_btnSaveToFile.insets = new Insets(0, 0, 0, 5);
		gbc_btnSaveToFile.gridx = 2;
		gbc_btnSaveToFile.gridy = 6;
		add(btnSaveToFile, gbc_btnSaveToFile);

		btnExecute.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				execute();
			}
		});

		btnSaveToFile.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				save();
			}
		});

		changedAlgorithm();
	}

	public PanelAlgorithmsDetails getPanelAlgo() {
		return (PanelAlgorithmsDetails) comboBoxAlgorithm.getSelectedItem();
	}

	public void execute() {
		getPanelAlgo().execute(img);
		progressBar.setIndeterminate(true);
	}

	public void changedAlgorithm() {
		panelHyperParams.removeAll();
		PanelAlgorithmsDetails algo = getPanelAlgo();
		panelHyperParams.add(algo);
		this.revalidate();
	}

	public void doReset() {
		panelImg.setImage(img);
	}

	public void save() {
		IDrawable saveImage = panelImg.getImage();

		BufferedImage newImg = new BufferedImage(saveImage.getWidth(),
				saveImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
		Graphics2D g2 = (Graphics2D) newImg.getGraphics();
		saveImage.draw(g2);
		g2.dispose();

		JFileChooser fc = new JFileChooser(".");
		fc.setFileFilter(new FileNameExtensionFilter("PNG Files(*.png)",
				new String[] { "png" }));
		int retVal = fc.showSaveDialog(this);

		if (retVal == JFileChooser.APPROVE_OPTION) {
			File f = fc.getSelectedFile();
			try {
				ImageIO.write(newImg, "png", f);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		progressBar.setIndeterminate(false);
		PanelAlgorithmsDetails algo = getPanelAlgo();
		panelImg.setImage(algo.getImage());
	}
}
